﻿//-----------------------------------------------------------------------
// <copyright file="StatusUpdateWebPart.cs" company="Danny Jessee">
//     This code is released under the Microsoft Public License (Ms-PL).
//     For more information, see http://facebookwebparts.codeplex.com/license.
// </copyright>
//-----------------------------------------------------------------------
namespace FacebookWebParts
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using Microsoft.IdentityModel.Claims;
    using Microsoft.Office.Server;
    using Microsoft.Office.Server.UserProfiles;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebControls;
    
    /// <summary>
    /// Allows the current user to update his/her Facebook feed with a status message
    /// posted from SharePoint. Also updates the Facebook user's SharePoint user profile
    /// with this message.
    /// </summary>
    [ToolboxItemAttribute(false)]
    public class StatusUpdateWebPart : WebPart
    {
        /// <summary>
        /// String used to hold the Facebook Graph API AccessToken.
        /// </summary>
        private string accessToken = string.Empty;

        /// <summary>
        /// TextBox containing a user's status message.
        /// </summary>
        private TextBox txtStatus = new TextBox();

        /// <summary>
        /// TextBox to capture a link URL associated with a user's status message.
        /// </summary>
        private TextBox txtLinkUrl = new TextBox();

        /// <summary>
        /// TextBox to capture a link name associated with a user's status message.
        /// </summary>
        private TextBox txtLinkName = new TextBox();

        /// <summary>
        /// TextBox used to capture a link caption associated with a user's status message.
        /// </summary>
        private TextBox txtLinkCaption = new TextBox();

        /// <summary>
        /// TextBox used to capture a link description associated with a user's status message.
        /// </summary>
        private TextBox txtLinkDescription = new TextBox();

        /// <summary>
        /// TextBox used to capture a link image URL associated with a user's status message.
        /// </summary>
        private TextBox txtLinkImageUrl = new TextBox();

        /// <summary>
        /// Button allowing the user to submit a status message.
        /// </summary>
        private Button btnSubmit = new Button();

        /// <summary>
        /// Label used for displaying output and error information.
        /// </summary>
        private Label lblStatus = new Label();

        /// <summary>
        /// String value containing the Facebook AccessToken claim URI.
        /// </summary>
        private string accessTokenClaimUri = string.Empty;

        /// <summary>
        /// Gets or sets the string value containing the URI of the Facebook Graph API AccessToken claim.
        /// By default, this URI is http://www.facebook.com/claims/AccessToken.
        /// </summary>
        [WebBrowsable(true), Category("Custom Properties")]
        [WebDisplayName("Facebook Access Token Claim URI")]
        [Personalizable(PersonalizationScope.Shared)]
        public string FacebookAccessTokenClaimUri
        {
            get
            {
                if (string.IsNullOrEmpty(this.accessTokenClaimUri))
                {
                    this.accessTokenClaimUri = "http://www.facebook.com/claims/AccessToken";
                }

                return this.accessTokenClaimUri;
            }

            set
            {
                this.accessTokenClaimUri = value;
            }
        }

        /// <summary>
        /// Gets or sets the string value containing the Facebook Graph API AccessToken.
        /// </summary>
        private string FacebookAccessToken
        {
            get
            {
                if (string.IsNullOrEmpty(this.accessToken))
                {
                    try
                    {
                        IClaimsPrincipal claimsPrincipal = Page.User as IClaimsPrincipal;
                        IClaimsIdentity claimsIdentity = (IClaimsIdentity)claimsPrincipal.Identity;

                        this.accessToken = (from c in claimsIdentity.Claims
                                            where c.ClaimType.Equals(this.FacebookAccessTokenClaimUri)
                                            select c.Value).FirstOrDefault();
                    }
                    catch (Exception)
                    {
                        this.accessToken = string.Empty;
                    }
                }

                return this.accessToken;
            }

            set
            {
                this.accessToken = value;
            }
        }

        /// <summary>
        /// Adds the TextBox and Button controls to the web part's Controls collection.
        /// </summary>
        protected override void CreateChildControls()
        {
            this.Controls.Add(new LiteralControl("<font size=4>Post a Status Update</font><br/>"));
            this.Controls.Add(this.lblStatus);
            this.Controls.Add(new LiteralControl("<br/><font size=2>Status:</font><br/>"));
            this.txtStatus.Width = Unit.Pixel(300);
            this.txtStatus.TextMode = TextBoxMode.MultiLine;
            this.txtStatus.Rows = 4;
            this.Controls.Add(this.txtStatus);
            this.Controls.Add(new LiteralControl("<br/><br/>"));
            this.Controls.Add(new LiteralControl("<font size=2>Link URL:</font><br/>"));
            this.txtLinkUrl.Width = Unit.Pixel(300);
            this.Controls.Add(this.txtLinkUrl);
            this.Controls.Add(new LiteralControl("<br/>"));
            this.Controls.Add(new LiteralControl("<font size=2>Link Name:</font><br/>"));
            this.txtLinkName.Width = Unit.Pixel(300);
            this.Controls.Add(this.txtLinkName);
            this.Controls.Add(new LiteralControl("<br/>"));
            this.Controls.Add(new LiteralControl("<font size=2>Link Caption:</font><br/>"));
            this.txtLinkCaption.Width = Unit.Pixel(300);
            this.Controls.Add(this.txtLinkCaption);
            this.Controls.Add(new LiteralControl("<br/>"));
            this.Controls.Add(new LiteralControl("<font size=2>Link Description:</font><br/>"));
            this.txtLinkDescription.Width = Unit.Pixel(300);
            this.Controls.Add(this.txtLinkDescription);
            this.Controls.Add(new LiteralControl("<br/>"));
            this.Controls.Add(new LiteralControl("<font size=2>Link Image URL:</font><br/>"));
            this.txtLinkImageUrl.Width = Unit.Pixel(300);
            this.Controls.Add(this.txtLinkImageUrl);
            this.Controls.Add(new LiteralControl("<br/>"));

            this.btnSubmit.Text = "Submit";
            this.btnSubmit.Click += new EventHandler(this.BtnSubmit_Click);
            this.Controls.Add(this.btnSubmit);
            this.Controls.Add(new LiteralControl("<br/>"));
        }

        /// <summary>
        /// When pressed, posts the status update to the current Facebook user's feed.
        /// </summary>
        /// <param name="sender">Default object parameter.</param>
        /// <param name="e">Default EventArgs parameter.</param>
        private void BtnSubmit_Click(object sender, EventArgs e)
        {
            try
            {
                if (!string.IsNullOrEmpty(this.FacebookAccessTokenClaimUri))
                {
                    var client = new Facebook.FacebookClient(this.FacebookAccessToken);
                    Dictionary<string, object> dict = new Dictionary<string, object>();
                    dict.Add("message", this.txtStatus.Text);
                    if (!string.IsNullOrEmpty(this.txtLinkUrl.Text))
                    {
                        dict.Add("link", this.txtLinkUrl.Text);
                    }

                    if (!string.IsNullOrEmpty(this.txtLinkImageUrl.Text))
                    {
                        dict.Add("picture", this.txtLinkImageUrl.Text);
                    }

                    if (!string.IsNullOrEmpty(this.txtLinkName.Text))
                    {
                        dict.Add("name", this.txtLinkName.Text);
                    }

                    if (!string.IsNullOrEmpty(this.txtLinkCaption.Text))
                    {
                        dict.Add("caption", this.txtLinkCaption.Text);
                    }

                    if (!string.IsNullOrEmpty(this.txtLinkDescription.Text))
                    {
                        dict.Add("description", this.txtLinkDescription.Text);
                    }

                    client.PostAsync("me/feed", dict);

                    // Also update the SharePoint profile with the status
                    Guid siteId = SPContext.Current.Site.ID;
                    using (SPSite site = new SPSite(siteId, SPUserToken.SystemAccount))
                    {
                        // This code may need to run in a different context depending
                        //  on the permissions you have set for your User Profile Service Application
                        SPServiceContext sc = SPServiceContext.GetContext(site);
                        UserProfileManager userProfileMangager = new UserProfileManager(sc);
                        UserProfile profile = userProfileMangager.GetUserProfile(true);
                        profile[PropertyConstants.StatusNotes].Value = this.txtStatus.Text;
                        profile.Commit();
                    }

                    this.lblStatus.Text = "<font color=green><b>Status and user profile successfully updated!</b></font>";
                }
                else
                {
                    this.Controls.Add(new LiteralControl("<font size=2>Please ensure the Facebook AccessToken claim URI is populated and that you are signed in via Facebook.</font>"));
                }
            }
            catch (Exception ex)
            {
                this.lblStatus.Text = "<font color=red><b>" + ex.Message + "<br/>" + ex.StackTrace + "</b></font>";
            }
        }
    }
}